package com.deer.wms.instock.web;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deer.wms.ASN.manage.constant.AsnManageConstant;
import com.deer.wms.ASN.manage.dao.AsnDetailMapper;
import com.deer.wms.ASN.manage.dao.AsnMasterMapper;
import com.deer.wms.ASN.manage.model.AsnCodeDetail;
import com.deer.wms.ASN.manage.model.asn.AsnDetail;
import com.deer.wms.ASN.manage.model.asn.AsnMaster;
import com.deer.wms.ASN.manage.model.asn.AsnMasterDto;
import com.deer.wms.ASN.manage.model.in.AcceptRecord;
import com.deer.wms.ASN.manage.service.AcceptRecordService;
import com.deer.wms.ASN.manage.service.AsnCodeDetailService;
import com.deer.wms.ASN.manage.service.AsnDetailService;
import com.deer.wms.ASN.manage.service.AsnMasterService;
import com.deer.wms.base.system.constant.BaseSystemConstant;
import com.deer.wms.base.system.dao.SuppInfoMapper;
import com.deer.wms.base.system.model.Cell.CellInfo;
import com.deer.wms.base.system.model.Cell.CellInfoDto;
import com.deer.wms.base.system.model.Supplier.SupplierInfo;
import com.deer.wms.base.system.service.AreaInfoService;
import com.deer.wms.base.system.service.CellInfoService;
import com.deer.wms.base.system.service.ItemInfoService;
import com.deer.wms.busine.tactic.model.Upper.UpperTacticDetailDto;
import com.deer.wms.busine.tactic.service.UpperTacticService;
import com.deer.wms.instock.constant.InStockConstant;
import com.deer.wms.instock.dao.TransferBillMapper;
import com.deer.wms.instock.model.Allot.TransferBillCriteria;
import com.deer.wms.instock.model.transfer.*;
import com.deer.wms.instock.service.TransferBillService;
import com.deer.wms.instock.service.enter.StrategyEnterService;
import com.deer.wms.intercept.annotation.NoRepeatSubmit;
import com.deer.wms.intercept.annotation.User;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.model.IDS;
import com.deer.wms.inventory.model.Inventory.Inventory;
import com.deer.wms.inventory.model.Inventory.InventoryCriteria;
import com.deer.wms.inventory.model.Inventory.InventoryDto;
import com.deer.wms.inventory.model.Inventory.InventoryExcel;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.core.result.Result;
import com.deer.wms.project.root.core.result.ResultGenerator;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.util.Excel;
import com.deer.wms.project.root.util.PageUtils;
import com.deer.wms.project.root.util.StringUtils;
import com.deer.wms.system.manage.model.dept.Dept;
import com.deer.wms.system.manage.service.CodeRuleService;
import com.deer.wms.system.manage.service.DeptService;
import com.deer.wms.ware.task.constant.WareTaskConstant;
import com.deer.wms.ware.task.model.ErpPushLogInfo;
import com.deer.wms.ware.task.model.SO.SoDetail;
import com.deer.wms.ware.task.model.SO.SoMaster;
import com.deer.wms.ware.task.model.pushErp.beasAssist.BaseAssist;
import com.deer.wms.ware.task.service.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

import static com.deer.wms.project.root.util.PageUtils.getStart;

/**
 * @author : wei
 * @since : 2022-01-08 20:37:44
 **/
@Api(description = "转移单API接口")
@RestController
@RequestMapping("/transfer")
public class TransferBillController {

    @Autowired
    private TransferBillService transferBillService;
    @Autowired
    private AcceptRecordService acceptRecordService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private PickTaskService pickTaskService;
    @Autowired
    private CellInfoService cellInfoService;
    @Autowired
    private UpperTacticService upperTacticService;
    @Autowired
    private ItemInfoService itemInfoService;

    @Autowired
    private SuppInfoMapper suppInfoMapper;

    @Autowired
    private DeptService deptService;

    @Autowired
    private AsnMasterMapper asnMasterMapper;

    @Autowired
    private TransferBillMapper transferBillMapper;
    @Autowired
    private AsnDetailMapper asnDetailMapper;

    @Autowired
    private AsnMasterService asnMasterService;


    @Autowired
    private StrategyEnterService strategyEnterService;
    @Autowired
    private AsnCodeDetailService asnCodeDetailService;
    @Autowired
    private CodeRuleService codeRuleService;

    @Autowired
    private AsnDetailService asnDetailService;
    @Autowired
    private AreaInfoService areaInfoService;




    @ApiOperation(value = "生成装箱单", notes = "PDA")
    @PostMapping("create/pack/box")
    @Transactional
    public Result createPackBoxForPda(@RequestBody PackBoxData packBoxData, @ApiIgnore @User CurrentUser currentUser) {

        //Step1.解析前台传来的数据PackBoxData
        String acceptRecordCode = packBoxData.getAcceptRecordCode();
        AcceptRecord acceptRecord = acceptRecordService.getOneByField("accept_record_code", acceptRecordCode);
        List<PackBox> list = packBoxData.getList();
        //Step2.准备数据
        List<TransferBill> transferBills = new ArrayList<>();
        for (PackBox packBox : list) {
            TransferBill transferBill = new TransferBill();
            //仓库
            transferBill.setWareId(acceptRecord.getWareId());
            //转移单类型
            transferBill.setBillType(InStockConstant.TRANS_TYPE_PACK_BOX);
            //来源库位 收货区库位   无目标库位
            transferBill.setFromCellCode(acceptRecord.getCellCode());
            transferBill.setToCellCode(acceptRecord.getCellCode());
            transferBill.setAsnStockId(acceptRecord.getAsnStockId());
            transferBill.setAsnStockName(acceptRecord.getAsnStockName());
            //无来源容器  目标容器
            transferBill.setToBoxCode(packBox.getBoxCode());
            transferBill.setItemCode(packBox.getItemCode());
            transferBill.setBatchName(packBox.getBatchName());
            transferBill.setPackDetailId(acceptRecord.getPackDetailId());
            transferBill.setQty(new BigDecimal(packBox.getQty()));
            //标记冻结解冻标识 
            if (AsnManageConstant.ACCEPT_QC_STATE_TODO.equals(acceptRecord.getQcState())) {
                //说明是待检的物料
                transferBill.setFreezeFlag(AsnManageConstant.ACCEPT_QC_STATE_TODO);
            }
            //确认人
            transferBill.setConfirmUserId(currentUser.getUserId());
            transferBill.setConfirmUserName(currentUser.getUserName());
            //收货单编码
            transferBill.setUda1(acceptRecordCode);
            transferBill.setUda2(acceptRecord.getAsnDetailNo());
            transferBills.add(transferBill);
        }
        //Step3.保存
        transferBillService.saveAndConfirmTransferBill(transferBills);

        // 修改相应的收货单数据
        // 页面已完成装箱数量
        Double packedQty = 0.0;
        // 收货单创建时--已装箱数量为空
        if (acceptRecord.getPackedQuantity() == null) {
            acceptRecord.setPackedQuantity(0.0);
        }
        for (TransferBill packBill : transferBills) {
            // 每个箱装的数量进行累加
            packedQty += packBill.getQty().doubleValue();
        }
        // 页面装箱的数量+单据原本已装箱数量
        packedQty += acceptRecord.getPackedQuantity();
        // 更新已装箱数量
        acceptRecord.setPackedQuantity(packedQty);
        // 收货单信息更新
        acceptRecordService.saveOrUpdate(acceptRecord);

        return ResultGenerator.genSuccessResult();
    }


    @ApiOperation(value = "生成装箱单", notes = "PDA")
    @PostMapping("batch/create/box")
    @Transactional
//    @NoRepeatSubmit
    public Result batchCreatePackBox(@RequestBody PackBoxData packBoxData, @ApiIgnore @User CurrentUser currentUser) {
        transferBillService.batchCreatePackBox(packBoxData, currentUser);
//        throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "来源容器不允许为空");

        return ResultGenerator.genSuccessResult();
    }



    @ApiOperation(value = "生成装箱单", notes = "Web")
    @PostMapping("batch/create/boxWeb")
    @Transactional
//    @NoRepeatSubmit
    public Result createboxWeb(@RequestBody PackBox packBoxData, @ApiIgnore @User CurrentUser currentUser) {
        List<AcceptRecord> acceptList = packBoxData.getAcceptList();
        Set<String> collect = acceptList.stream().map(item -> item.getAsnBillNo()).collect(Collectors.toSet());
        if (collect.size() > 1) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "不同任务单不可以重复提交");
        }

        transferBillService.createboxWeb(packBoxData, currentUser);

        return ResultGenerator.genSuccessResult();
    }

    @ApiOperation(value = "上架", notes = "PDA")
    @PostMapping("create/upper")
    @Transactional(rollbackFor = Exception.class)
    public Result createUpperForPda(@RequestBody UpperData upperData, @ApiIgnore @User CurrentUser currentUser) {
        if (ObjectUtil.isEmpty(upperData.getCellCode())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "请扫描目标库位！");
        }
        Dept dept = new Dept();
        Integer supperId;
        //供应商名称
        if (ObjectUtil.isNotEmpty(upperData.getSupplierId()) && upperData.getSupplierId() != 0) {
            SupplierInfo supplierInfo = suppInfoMapper.selectById(upperData.getSupplierId());
            if (ObjectUtil.isNotEmpty(supplierInfo)) {
                upperData.setSupplierName(supplierInfo.getSupName());

            }
        }
        //部门名称
        if (ObjectUtil.isNotEmpty(upperData.getDeptId())) {
            dept = deptService.getById(upperData.getDeptId());
            upperData.setDeptName(dept.getDeptName());
        }
        String oldBoxCode = "";
        TransferBill transferBill = transferBillService.getOne(new QueryWrapper<TransferBill>().
                eq("to_box_code", upperData.getBoxCode()
                )
        );

        oldBoxCode = transferBill.getToBoxCode();

        transferBill.setState(2);
        transferBill.setFromBoxCode(transferBill.getFromBoxCode());
        transferBill.setToBoxCode(null);
        transferBillService.updateById(transferBill);

        transferBill.setFromBoxCode(oldBoxCode);
        //目标库存
        transferBill.setToCellCode(upperData.getCellCode());
        transferBill.setToBoxCode(upperData.getBoxCode());
        transferBill.setId(null);
        transferBill.setBillType(2);
        transferBill.setState(0);
        List<TransferBill> transferBills = new ArrayList<>();
        transferBill.setFromBoxCode(null);
        transferBill.setToBoxCode(oldBoxCode);
        transferBills.add(transferBill);


        //生成库存事务
        transferBillService.confirmTransferBill(transferBills);

//        transferBillService.save(transferBill);
//        transferBillService.batchBill(transferBill);
//
//
//        Integer erpAreaId = cellInfoService.findbyCellCode(upperData.getCellCode());
//        //初始化回传数据
//        AsnMaster asnMaster = asnMasterMapper.selectOne(new QueryWrapper<AsnMaster>().eq("bill_no", transferBill.getUda1()));
//        BaseAssist enterAssist = new BaseAssist();
//        enterAssist.setFromBoxCode(transferBill.getFromBoxCode());
//        enterAssist.setDeptId(dept.getDeptId());
//        enterAssist.setCellCode(upperData.getCellCode());
//        enterAssist.setBatchName(transferBill.getBatchName());
//        enterAssist.setErpAreaId(erpAreaId);
//        enterAssist.setSupplierId(upperData.getSupplierId());
//        List<AsnDetail> asnDetails = new ArrayList<>();
//        List<AsnCodeDetail> asnCodeDetails = asnCodeDetailService.list(new QueryWrapper<AsnCodeDetail>().eq("box_code", oldBoxCode));
//        for (AsnCodeDetail asnCodeDetail : asnCodeDetails) {
//            Inventory inventory = inventoryService.getOne(new QueryWrapper<Inventory>()
//                    .eq("box_code", oldBoxCode)
//                    .eq("item_code", asnCodeDetail.getItemCode())
//            );
//            AsnDetail asnDetail = new AsnDetail();
//            BeanUtils.copyProperties(asnCodeDetail, asnDetail);
//
//            //todo  vmi待检仓 直发虚仓
//            if (ObjectUtil.isEmpty(asnDetail.getStockId()) || (asnDetail.getStockId() != 471713 && asnDetail.getStockId() != 1111427)) {
//                //回传数量直接拉满
//                asnCodeDetail.setPushErpQty(asnCodeDetail.getQty());
//            }
//            asnDetail.setErpStockId(inventory.getAsnStockId());
//            asnDetail.setStockId(erpAreaId); //仓库id
//            asnDetail.setErpStockId(inventory.getAsnStockId()); //判断是否是虚仓
//            asnDetail.setBatchName(inventory.getBatchName());
//            asnDetails.add(asnDetail);
//        }
//        strategyEnterService.resolveAsn(asnMaster, asnDetails, enterAssist);
//        throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "收货单不为新建状态，不可确认!");


        return ResultGenerator.genSuccessResult();
    }


    @ApiOperation(value = "上架", notes = "PDA")
    @PostMapping("create/upperAsn")
    @Transactional(rollbackFor = Exception.class)
    public Result upperAsn(@RequestBody UpperData upperData, @ApiIgnore @User CurrentUser currentUser) {
        transferBillService.upperAsn(upperData, currentUser);


//
//        transferBill.setFromBoxCode(oldBoxCode);
//        //目标库存
//        transferBill.setToCellCode(upperData.getCellCode());
//        transferBill.setToBoxCode(upperData.getBoxCode());
//        transferBill.setId(null);
//        transferBill.setBillType(2);
//        transferBillService.save(transferBill);
//        transferBillService.batchBill(transferBill);

//
//
//        //初始化回传数据
//        AsnMaster asnMaster = asnMasterMapper.selectOne(new QueryWrapper<AsnMaster>().eq("bill_no", transferBill.getUda1()));
//        BaseAssist enterAssist = new BaseAssist();
//        enterAssist.setFromBoxCode(transferBill.getFromBoxCode());
//        enterAssist.setDeptId(dept.getDeptId());
//        enterAssist.setCellCode(upperData.getCellCode());
//        enterAssist.setBatchName(transferBill.getBatchName());
//        enterAssist.setErpAreaId(erpAreaId);
//        enterAssist.setSupplierId(upperData.getSupplierId());
//        List<AsnDetail> asnDetails = new ArrayList<>();
//        List<AsnCodeDetail> asnCodeDetails = asnCodeDetailService.list(new QueryWrapper<AsnCodeDetail>().eq("box_code", oldBoxCode));
//        for (AsnCodeDetail asnCodeDetail : asnCodeDetails) {
//            Inventory inventory = inventoryService.getOne(new QueryWrapper<Inventory>()
//                    .eq("box_code", oldBoxCode)
//                    .eq("item_code", asnCodeDetail.getItemCode())
//            );
//            AsnDetail asnDetail = new AsnDetail();
//            BeanUtils.copyProperties(asnCodeDetail, asnDetail);
//
//            //todo  vmi待检仓 直发虚仓
//            if (ObjectUtil.isEmpty(asnDetail.getStockId()) || (asnDetail.getStockId() != 471713 && asnDetail.getStockId() != 1111427)) {
//                //回传数量直接拉满
//                asnCodeDetail.setPushErpQty(asnCodeDetail.getQty());
//            }
//            asnDetail.setErpStockId(inventory.getAsnStockId());
//            asnDetail.setStockId(erpAreaId); //仓库id
//            asnDetail.setErpStockId(inventory.getAsnStockId()); //判断是否是虚仓
//            asnDetail.setBatchName(inventory.getBatchName());
//            asnDetails.add(asnDetail);
//        }
//
//        throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "收货单不为新建状态，不可确认!");


        return ResultGenerator.genSuccessResult();
    }


    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    @GetMapping("bathCellCode")
    @ApiOperation(value = "转移")
    public void bathCellCode() {
        transferBillService.findCodes();

    }

    @ApiOperation(value = "转移", notes = "PDA")
    @PostMapping("create/transfer")
    public Result createTransferForPda(@RequestBody Upper upper, @ApiIgnore @User CurrentUser currentUser) {
        //Step1.准备数据

        //来源容器库存
        List<Inventory> boxIvt = inventoryService.listByIds(Arrays.asList(upper.getInventoryIds().split(",")));

        if (ObjectUtil.isNull(boxIvt)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "根据容器号：" + upper.getBoxCode() + "未找到对应的库存");
        }
        Set<String> notTransfer = boxIvt.stream().filter(item -> item.getAllotQuantity() > 0 || item.getFreezeQuantity() > 0).map(Inventory::getItemCode).collect(Collectors.toSet());
        if (ObjectUtil.isNotEmpty(notTransfer)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, StringUtils.join(notTransfer,",")+"物料未拣货完毕，不可转移");
        }


        //判断目标库位是否合法
        CellInfo cellInfo = cellInfoService.getOneByField("cell_code", upper.getCellCode());
        if (ObjectUtil.isNull(cellInfo)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未查询到目标库位:[" + upper.getCellCode() + "]!");
        }
        Integer erpAreaId = boxIvt.listIterator().next().getErpAreaId();
        Integer toErpAreaId = cellInfoService.findbyCellCode(upper.getToBoxCode());
        if (erpAreaId.equals(toErpAreaId)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "不同仓库不能容器转移");
        }
        for (Inventory inventory : boxIvt) {
            TransferBill transferBill = new TransferBill();
            //转移单类型
            transferBill.setBillType(InStockConstant.TRANS_TYPE_MOVE);
            //仓库
            transferBill.setWareId(inventory.getWareId());
            //来源库位
            transferBill.setFromCellCode(inventory.getCellCode());
            //目标库位
            transferBill.setToCellCode(upper.getCellCode());
            //来源容器
            transferBill.setFromBoxCode(upper.getBoxCode());
            transferBill.setInventoryId(inventory.getInventoryId());
            transferBill.setToBoxCode(upper.getToBoxCode());
            transferBill.setItemCode(inventory.getItemCode());
            transferBill.setBatchName(inventory.getBatchName());
            transferBill.setPackDetailId(inventory.getPackDetailId());
            transferBill.setQty(new BigDecimal(inventory.getQuantity()));
            //确认人
            transferBill.setConfirmUserId(currentUser.getUserId());
            transferBill.setConfirmUserName(currentUser.getUserName());
            //Step2.保存
            transferBillService.saveAndConfirmTransferBill(ListUtil.toList(transferBill));
        }


        return ResultGenerator.genSuccessResult();
    }

    @ApiOperation(value = "查询装箱单")
    @GetMapping("/packwork/select")
    public Result selectPackWorkList(TransferBillCriteria criteria) {
        // 设置单据类型
        criteria.setBillType(InStockConstant.TRANS_TYPE_PACK_BOX);
        // 设置页面的分页条件
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());

        // 根据条件查询的装箱单数据
        List<TransferBill> transferBills = transferBillService.selectBillList(criteria);

        // 封装分页的数据
        PageInfo pageInfo = new PageInfo(transferBills);
        // 返回成功的结果
        return ResultGenerator.genSuccessResult(pageInfo);
    }


    @ApiOperation(value = "容器编码查是否为其他类型入库")
    @GetMapping("/packwork/findByCode")
    public Result selectPackWorkList(String billNo) {

        AsnMaster asnMaster = asnMasterService.getOne(new QueryWrapper<AsnMaster>().eq("bill_no", billNo));

//        if (ObjectUtil.isEmpty(code)) {
//            return null;
//        }
//        Map<String, Object> map = acceptRecordService.finbyCode(code);
        return ResultGenerator.genSuccessResult(asnMaster);
    }

    @ApiOperation(value = "查询上架单")
    @GetMapping("/putaway/select")
    public Result selectPackingList(TransferBillCriteria criteria) {
        // 设置单据类型
        criteria.setBillType(InStockConstant.TRANS_TYPE_UPPER);
        // 设置页面的分页条件
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        // 根据条件查询上架单数据
        List<TransferBill> transferBills = transferBillService.selectBillList(criteria);
        // 封装分页的数据
        PageInfo pageInfo = new PageInfo(transferBills);
        // 返回成功的结果
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @ApiOperation(value = "查询转移单")
    @GetMapping("/transferBill/list")
    public Result selectTransferBill(TransferBillCriteria criteria) {
        // 设置单据类型--4(转移单)
        criteria.setBillType(InStockConstant.TRANS_TYPE_MOVE);
        // 根据条件查询上架单数据
        List<TransferBill> transferBills = transferBillService.selectBillList(criteria);
        // 设置页面的分页条件
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        // 封装分页的数据
        PageInfo pageInfo = new PageInfo(transferBills);
        // 返回成功的结果
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @PostMapping("/transferBill/insert")
    @ApiOperation(value = "添加转移单", notes = "添加转移单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public Result addTransferBill(@RequestBody TransferBillCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            // 没有登录
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER, null);
        }
        List<TransferBill> transferBills = new ArrayList<>();
        TransferBill transferBill = new TransferBill();
        //仓库
        transferBill.setWareId(criteria.getWareId());
        //转移单类型
        transferBill.setBillType(InStockConstant.TRANS_TYPE_MOVE);
        //来源库位 收货区库位
        Inventory boxIvt = inventoryService.getOneByField("box_code", criteria.getFromBoxCode());
        if (ObjectUtil.isNull(boxIvt)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "根据容器号：" + criteria.getFromBoxCode() + "未找到对应的库存");
        }
        //FIXME: 这里写死，冻结的物料不能转移
        if (InventoryConstant.TRANSACT_STATE_UNNORMAL.equals(boxIvt.getState())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器内物料未质检，禁止上架!");
        }
        transferBill.setFromCellCode(boxIvt.getCellCode());
        //目标库位
        transferBill.setToCellCode(criteria.getToCellCode());
        //来源容器
        transferBill.setFromBoxCode(criteria.getFromBoxCode());
        transferBill.setItemCode(boxIvt.getItemCode());
        transferBill.setBatchName(boxIvt.getBatchName());
        transferBill.setPackDetailId(boxIvt.getPackDetailId());
        transferBill.setQty(new BigDecimal(boxIvt.getQuantity()));
        //标记冻结解冻标识
        if (boxIvt.getFreezeQuantity() > 0) {
            //说明是待检的物料
            transferBill.setFreezeFlag(AsnManageConstant.ACCEPT_QC_STATE_TODO);
        }
        //确认人
        transferBill.setConfirmUserId(currentUser.getUserId());
        transferBill.setConfirmUserName(currentUser.getUserName());
        transferBill.setConfirmTime(DateUtil.now());
        transferBills.add(transferBill);
        //Step2.保存
        transferBillService.createTransferBill(transferBills);
        return ResultGenerator.genSuccessResult();
    }


    @PostMapping("/PackWork/insert")
    @ApiOperation(value = "添加装箱单", notes = "添加装箱单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public Result addPackWork(@RequestBody TransferBillCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            // 没有登录
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER, null);
        }
        // 数据复制
        TransferBill transferBill = new TransferBill();
        // 装箱的数据来源库位和目标库位一样
        BeanUtils.copyProperties(criteria, transferBill);
        transferBill.setToCellCode(criteria.getFromCellCode());
        // 设置操作人员编号
        transferBill.setConfirmUserId(currentUser.getUserId());
        transferBill.setConfirmUserName(currentUser.getUserName());
        transferBill.setConfirmTime(DateUtil.now());
        // 设置转移单类型
        transferBill.setBillType(InStockConstant.TRANS_TYPE_PACK_BOX);
        // 准备数据
        List<TransferBill> transferBills = new ArrayList<>();
        transferBills.add(transferBill);
        // 执行保存的方法 saveAndConfirmTransferBill 保存会直接确认不使用这个方法
        transferBillService.createTransferBill(transferBills);
        // 新增成功返回消息
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/transferBill/updateState")
    @ApiOperation(value = "转移单确认", notes = "转移单确认")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public Result updateState(@RequestBody TransferBillCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            // 没有登录
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER, null);
        }
//        // 准备数据
//        criteria.setBillType(InStockConstant.TRANS_TYPE_MOVE);
        List<TransferBill> transferBills = transferBillService.selectBillList(criteria);
        // 执行转移单确认的方法
        transferBillService.confirmTransferBill(transferBills);
        // 新增成功返回消息
        return ResultGenerator.genSuccessResult();
    }

    @ApiOperation(value = "上架推荐库位")
    @GetMapping("/upper/recommend")
    public Result recommendUpperCellForPDA(@RequestParam String boxCode) {
        //Step1.校验容器库存是否是待收货区的
        InventoryCriteria inventoryCriteria = new InventoryCriteria();
        inventoryCriteria.setBoxCode(boxCode);
        inventoryCriteria.setPageNum(getStart(inventoryCriteria));
        List<InventoryDto> list = inventoryService.findList(inventoryCriteria);
        if (list.size() == 0) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器：[" + boxCode + "]未查询到库存");
        }
        if (ObjectUtil.notEqual(BaseSystemConstant.CELL_USE_TYPE_ACCEPT.toString(), list.get(0).getCellUseType())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器：[" + boxCode + "]已上架");
        }
//        if (list.size() > 1) {
//            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器：[" + boxCode + "]存在多条数据");
//        }

        //Step2.找到对应的上架策略
        InventoryDto inventoryDto = list.get(0);
        String itemCode = inventoryDto.getItemCode();
        List<UpperTacticDetailDto> upperTacticDetails = itemInfoService.findUpperTacticDetails(itemCode);

        //Step3.根据策略找到满足条件的库位
        List<CellInfoDto> recommendUpperCells = new ArrayList<>();
        for (UpperTacticDetailDto upperTacticDetail : upperTacticDetails) {
            recommendUpperCells = cellInfoService.getRecommendUpperCells(upperTacticDetail);
            //暂时只处理一个
            break;
        }
        for (CellInfoDto recommendUpperCell : recommendUpperCells) {
            Integer boxNum = inventoryService.getBoxNumInCell(recommendUpperCell.getCellCode());
            recommendUpperCell.setBoxNum(boxNum);
        }

        return ResultGenerator.genSuccessResult(recommendUpperCells);
//        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/findByboxCode")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public Result findByboxCode(String boxCode, String billNo) {
        if (ObjectUtil.isEmpty(boxCode)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器编码不能为空！");
        }

        QueryWrapper<Inventory> queryWrapper = new QueryWrapper();
        queryWrapper.eq(ObjectUtil.isNotEmpty(billNo), "asn_bill_no", billNo);
        queryWrapper.eq("box_code", boxCode);
        queryWrapper.eq("cell_code", 285000);
        List<Inventory> list = inventoryService.list(queryWrapper);
        return ResultGenerator.genSuccessResult(list);
    }


    @GetMapping("saveBillOutInfo")
    public Result saveBillOutInfo(String date) {
        Map<String, Object> map = new HashMap<>();
        map.put("dateFrom", date);
        transferBillService.saveBillOutInfo(map);
        return ResultGenerator.genSuccessResult();
    }



    @PostMapping("/updateErpLog/{id}")
    public Result updateErpLog(@RequestBody List<ErpPushLogInfo> erpPushLogInfo, @PathVariable Integer id) {
        transferBillService.updateErpLog(erpPushLogInfo, id);
        return ResultGenerator.genSuccessResult();
    }


    @GetMapping("input")
    public void input(MultipartFile file) {
   // List<IDS> ids = Excel.readExcelFile(file.getInputStream(), IDS.class, file.getOriginalFilename());
   // Set<Integer> collect = ids.stream().map(IDS::getId).collect(Collectors.toSet());
        Map<String, Object> asnMap = new HashMap<>();
        asnMap.put("dateFrom", null);
        asnMasterService.savePurchaseOrder(asnMap);

    }

    @Autowired
    private SoMasterService soMasterService;

    @Autowired
    private SoDetailService soDetailService;

    @GetMapping("outPut")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    @Transactional
    public void outPut(Integer startPage, Integer endPage) {

        List<Integer> list = new ArrayList<>();
        for (int i = startPage; i <= endPage; i++) {
            int finalI = i;
            CompletableFuture.runAsync(() -> {
                Map<String, Object> asnMap = new HashMap<>();
                asnMap.put("currentPage", finalI);
                asnMap.put("pageSize", 1000);
                asnMap.put("includeClosed", true);
                asnMap.put("billTypeId", 88);
                transferBillService.saveBillOutInfo(asnMap);
            });
       }


}


//    @GetMapping("outPut")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
//    })
//    @Transactional
//    public void outPut(Integer startPage, Integer endPage) {
//
//        List<Integer> list = new ArrayList<>();
//        for (int i = startPage; i <= endPage; i++) {
//            int finalI = i;
////            CompletableFuture.runAsync(() -> {
//            Map<String, Object> asnMap = new HashMap<>();
//            asnMap.put("currentPage", i);
//            asnMap.put("pageSize", 1000);
//            asnMap.put("includeClosed", true);
//            transferBillService.saveBillOutInfo(asnMap);
////            });
//        }
//    }


    @GetMapping("saveBath")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public void saveBathInv() {
        transferBillService.saveBathInv();
    }



    @GetMapping("bath")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public void bath() {
        transferBillService.batch();
    }


    /**
     * 通过单号查询单子状态--并且更新
     */
    @GetMapping("/findStateByBillNo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)
    })
    public Result findStateByBillNo(String billNo, String type) {
        // 通过入库任务单号查询库存 和 入库任务
        String msg = "";
        QueryWrapper<Inventory> queryWrapper = new QueryWrapper();
        queryWrapper.eq(ObjectUtil.isNotEmpty(billNo), "asn_bill_no", billNo);
        List<Inventory> inventories = inventoryService.list(queryWrapper);
        // 入库总数量
        Double qty = inventories.stream().mapToDouble(Inventory::getQuantity).sum();
        AsnMasterDto asnMaster = asnMasterService.findByBillNo(billNo);
        List<AsnDetail> details = asnDetailService.findByBillNo(billNo);
        // 单据总数量
        Double detailQty = details.stream().mapToDouble(AsnDetail::getExpectQuantity).sum();
        // 根据查询的数据来进行判断
        // 1.没有查询到数据--任务单未收货 或者 任务单的物料都出库了
        if (inventories.size() < 1) {
            if (asnMaster.getAsnState() > 5) {
                // 物料都出库了--已上架
                msg = "任务单已上架";
            } else {
                // 未收货--状态不变
                msg = "任务单未收货";
            }
        } else if(detailQty>qty){
            // 2.查询到数据
            //  库存的总数量 与 入库任务明细的总数量 不相等 单据状态是未收货完成--状态不变
            msg = "任务单部分收货";
        } else {
            for(Inventory inventory:inventories){
                // 有数据的库存有冻结状态 并且 状态描述是未质检  单据状态是未质检完成--已收货
                if(inventory.getFreezeQuantity()>0 && "未质检".equals(inventory.getStateDis())){
                    msg = "任务单已收货";
                    break;
                }
            }
            if(!"任务单已收货".equals(msg)){
                for(Inventory inventory:inventories){
                    // 有数据没有容器的 单据状态 未装箱--已质检
                    if(ObjectUtil.isNull(inventory.getBoxCode())){
                        msg = "任务单已质检";
                        break;
                    }
                }
            }
            if(!"任务单已质检".equals(msg)&&!"任务单已收货".equals(msg)){
                for(Inventory inventory:inventories){
                    // 有的数据没有库位 单据状态 未上架--已装箱
                    if(ObjectUtil.isNull(inventory.getCellCode())){
                        msg = "任务单已装箱";
                        break;
                    }
                }
            }
            if(!"任务单已质检".equals(msg)&&!"任务单已收货".equals(msg)&&!"任务单已装箱".equals(msg)){
                    // 所有数据都有库位 已上架
                    msg = "任务单已上架";
            }
        }
        // 3.根据不同的查询返回不同的消息提示
        // type--0 来料暂收 1批量质检 2装箱上架 3推荐上架
        String retMsg="";
        if("来料暂收".equals(type)){
            if("任务单已质检".equals(msg)||"任务单已收货".equals(msg)
                    ||"任务单已装箱".equals(msg)||"任务单已上架".equals(msg)){
                retMsg = "任务单已收货";
            }else{
                retMsg = "任务单不存在";
            }
        }else if("批量质检".equals(type)){
            if("任务单已质检".equals(msg)||"任务单已装箱".equals(msg)||"任务单已上架".equals(msg)){
                retMsg = "任务单已质检";
            }else{
                retMsg = msg;
            }
        } else if("装箱上架".equals(type)){
            if("任务单已装箱".equals(msg)||"任务单已上架".equals(msg)){
                retMsg = "任务单已装箱";
            }else{
                retMsg = msg;
            }
        }else if("推荐上架".equals(type)){
            if("任务单已上架".equals(msg)){
                retMsg = "任务单已上架";
            }else{
                retMsg = msg;
            }
        }

        return ResultGenerator.genSuccessResult(null);
    }

    @ApiOperation(value = "库存导出", notes = "库存导出")
    @GetMapping("/exportInventory")
    public Result exportInboundExcel(InventoryCriteria criteria, HttpServletResponse response) {
//        List<InventoryExcel> list = new ArrayList<>();
//        List<CompletableFuture<List<InventoryExcel>>> listFuture = new ArrayList<>();
//        //Step1.多线程请求后台
//        for (int i = 1; i < 11 ; i++) {
//            int finalI = i;
//            criteria.setPageNum((finalI - 1) * 10000);
//            criteria.setPageSize(10000);
//            InventoryCriteria inventoryCriteria = new InventoryCriteria();
//            BeanUtils.copyProperties(criteria, inventoryCriteria);
//            CompletableFuture<List<InventoryExcel>> future = CompletableFuture.supplyAsync(() -> {
//                return transferBillService.dowLoadList(inventoryCriteria);
//            });
//            listFuture.add(future);
//        }
//        //Step2. 遍历线程获取值
//        for (CompletableFuture<List<InventoryExcel>> future : listFuture) {
//            try {
//                list.addAll(future.get());
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            } catch (ExecutionException e) {
//                e.printStackTrace();
//            }
//
//        }

        List<InventoryExcel> inventoryExcels = transferBillService.dowLoadList(criteria);

//        System.out.println(list);
        Excel.outExcelFile(inventoryExcels,response,InventoryExcel.class);

//
//        String staticPath = fileSetting.getStaticFileDir();
//        String downloadPath = "\\download\\inventory.xls";
//        String modelPath = "\\model\\inventoryModel.xls";
//        try {
//            String modelFilePath = staticPath + modelPath;
//            String filePath = staticPath + downloadPath;
//
//            jxl.Workbook workbook = jxl.Workbook.getWorkbook(new java.io.File(modelFilePath));
//            WritableWorkbook copy = jxl.Workbook.createWorkbook(new java.io.File(filePath), workbook);
//
//            WritableSheet wSheet = copy.getSheet(0);
//            CellFormat format = wSheet.getCell(1, 1).getCellFormat();
//            DecimalFormat two = new DecimalFormat("#.##");
//
//            Double sum = 0.0;
//            for (int i = 0; i < list.size(); i++) {
//
//                wSheet.insertRow(i + 2);
//
//                InventoryDto inventory = list.get(i);
//
//                String indexStr = Integer.toString(i + 1);
//                String wareName = "-";
//                if (inventory.getWareName() != null) {
//                    wareName = inventory.getWareName();
//                }
//                String organizationName = "-";
//                if (inventory.getOrganizationName() != null) {
//                    organizationName = inventory.getOrganizationName();
//                }
//                String itemName = "-";
//                if (inventory.getItemName() != null) {
//                    itemName = inventory.getItemName();
//                }
//                String itemCode = "-";
//                if (inventory.getCellCode() != null) {
//                    itemCode = inventory.getItemCode();
//                }
//                String batchName = "-";
//                if (inventory.getBatchName() != null) {
//                    batchName = inventory.getBatchName();
//                }
//
//                String quantity = "-";
//                if (inventory.getQuantity() != null) {
//                    quantity = Double.toString(inventory.getQuantity());
//                }
//
//                String packDescribe = "-";
//                if (inventory.getPackDescribe() != null) {
//                    packDescribe = inventory.getPackDescribe();
//                }
//                String allotQuantity = "-";
//                if (inventory.getAllotQuantity() != null) {
//                    allotQuantity = Double.toString(inventory.getAllotQuantity());
//                }
//                String freezeQuantity = "-";
//                if (inventory.getFreezeQuantity() != null) {
//                    freezeQuantity = Double.toString(inventory.getFreezeQuantity());
//                }
//                String cellCode = "-";
//                if (inventory.getCellCode() != null) {
//                    cellCode = inventory.getCellCode();
//                }
//                String boxCode = "-";
//                if (inventory.getBoxCode() != null) {
//                    boxCode = inventory.getBoxCode();
//                }
//                String lpn = "-";
//                if (inventory.getLpn() != null) {
//                    lpn = inventory.getLpn();
//                }
//
//
//                Label indexLabel = new Label(0, i + 2, indexStr);
//                Label wareNameLabel = new Label(1, i + 2, wareName);
//                Label organizationNameLabel = new Label(2, i + 2, organizationName);
//                Label itemNameLabel = new Label(3, i + 2, itemName);
//                Label itemCodeLabel = new Label(4, i + 2, itemCode);
//                Label batchNameLabel = new Label(5, i + 2, batchName);
//                Label quantityLabel = new Label(6, i + 2, quantity);
//                Label packDescribeLabel = new Label(7, i + 2, packDescribe);
//                Label allotQuantityLabel = new Label(8, i + 2, allotQuantity);
//                Label freezeQuantityLabel = new Label(9, i + 2, freezeQuantity);
//                Label cellCodeLabel = new Label(10, i + 2, cellCode);
//                Label boxCodeLabel = new Label(11, i + 2, boxCode);
//                Label lpnLabel = new Label(12, i + 2, lpn);
//
//                indexLabel.setCellFormat(format);
//                wareNameLabel.setCellFormat(format);
//                organizationNameLabel.setCellFormat(format);
//                itemNameLabel.setCellFormat(format);
//                itemCodeLabel.setCellFormat(format);
//                batchNameLabel.setCellFormat(format);
//                quantityLabel.setCellFormat(format);
//                packDescribeLabel.setCellFormat(format);
//                allotQuantityLabel.setCellFormat(format);
//                freezeQuantityLabel.setCellFormat(format);
//                cellCodeLabel.setCellFormat(format);
//                boxCodeLabel.setCellFormat(format);
//                lpnLabel.setCellFormat(format);
//
//                wSheet.addCell(indexLabel);
//                wSheet.addCell(wareNameLabel);
//                wSheet.addCell(organizationNameLabel);
//                wSheet.addCell(itemNameLabel);
//                wSheet.addCell(itemCodeLabel);
//                wSheet.addCell(batchNameLabel);
//                wSheet.addCell(quantityLabel);
//                wSheet.addCell(packDescribeLabel);
//                wSheet.addCell(allotQuantityLabel);
//                wSheet.addCell(freezeQuantityLabel);
//                wSheet.addCell(cellCodeLabel);
//                wSheet.addCell(boxCodeLabel);
//                wSheet.addCell(lpnLabel);
//            }
//
//
//            String nowStr = "打印日期：" + DateUtils.getNowDateString();
//            Label dateLabel = new Label(0, list.size() + 3, nowStr);
//            dateLabel.setCellFormat(format);
//            wSheet.addCell(dateLabel);
//
//            copy.write();
//            copy.close();
//            workbook.close();
//
//        } catch (Exception e) {
//            e.printStackTrace();
//
//        } finally {
//        }

        return ResultGenerator.genSuccessResult();
    }



//    @PostMapping("importExl")
//    /**
//     *导入erp仓库信息
//     */
//    @ApiImplicitParams({@ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)})
//    public void inputErp(MultipartFile file) {
//        try {
//            List<Inventory> inventoryList = Excel.readExcelFile(file.getInputStream(), Inventory.class, file.getOriginalFilename());
//            List<String> billNos = inventoryList.stream().map(item -> item.getAsnBillNo()).collect(Collectors.toList());
//            List<AcceptRecord> acceptRecords = acceptRecordService.list(new QueryWrapper<AcceptRecord>().in("asn_bill_no", billNos));
//            List<Inventory> list = inventoryService.list(new QueryWrapper<Inventory>().in("asn_bill_no", billNos).eq("cell_code", 285000)
//            );
//            for (AcceptRecord acceptRecord : acceptRecords) {
//                acceptRecord.setPackedQuantity(acceptRecord.getQuantity());
//            }
//            for (Inventory inventory : list) {
//                inventory.setQuantity(0.00);
//                inventory.setCellCode("28500001");
//            }
//            acceptRecordService.updateBatchById(acceptRecords);
//            inventoryService.updateBatchById(list);
//            System.out.println(111);
//
////            List<Inventory> collect = inventoryList.stream().filter(item -> ObjectUtil.isNotEmpty(item.getErpAreaId())).collect(Collectors.toList());
////
////            for (Inventory inventory : collect) {
////                inventory.setWareId(285);
////                inventory.setWareName("如高高压");
////                inventory.setOrganizationId(-1);
////                inventory.setOrganizationName("自有");
////                inventory.setPackDetailId(33469);
////                inventory.setPackDescribe("件");
////                inventory.setBoxCode(generateCode());
////            }
////            inventoryService.updateBath(collect);
//
////            inventoryService.saveBatch(collect);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//    }


}
